﻿using UnityEngine;

namespace HotPlayer.Physic2D
{
    public static class MathUtils
    {
        /// <summary>
        /// 三叉积
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static Vector2 TripleProduct(Vector2 a, Vector2 b, Vector2 c)
        {
            // (AC x AB) x AB = AB(AB.dot(AC)) - AC(AB.dot(AB))
            var ac = Vector2.Dot(a, c);
            var bc = Vector2.Dot(b, c);
            return new Vector2(b.x * ac - a.x * bc, b.y * ac - a.y * bc);
        }

        /// <summary>
        /// abc三点组成的三角形是否包含p
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static bool Contains(Vector2 a, Vector2 b, Vector2 c, Vector2 p)
        {
            var ab = b - a;
            var bc = c - b;
            var ca = a - c;

            var cross1 = Cross(ab, p - a);
            var cross2 = Cross(bc, p - b);
            var cross3 = Cross(ca, p - c);

            var hasSameSign = (cross1 >= 0 && cross2 >= 0 && cross3 >= 0) ||
                              (cross1 <= 0 && cross2 <= 0 && cross3 <= 0);

            return hasSameSign;
        }

        /// <summary>
        /// 叉积
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static float Cross(Vector2 a, Vector2 b)
        {
            return a.x * b.y - a.y * b.x;
        }
        
        /// <summary>
        /// v到p的距离
        /// </summary>
        /// <param name="v"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static float Distance(Vector2 v, Vector2 p)
        {
            var perpendicular = Vector2.Perpendicular(v);
            return Mathf.Sqrt(ProductAtoB(perpendicular, p).sqrMagnitude);
        }

        /// <summary>
        /// a到b的向量到p的距离
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static float Distance(Vector2 a, Vector2 b, Vector2 p)
        {
            var perpendicular = Vector2.Perpendicular(a - b);
            return Mathf.Sqrt(ProductAtoB(perpendicular, p).sqrMagnitude);
        }

        /// <summary>
        /// 向量a在向量b上的投影
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static Vector2 ProductAtoB(Vector2 a, Vector2 b)
        {
            return Vector2.Dot(a, b) * b.normalized;
        }
    }
}